package com.ruoyi.charge.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.ruoyi.charge.common.GlobalConstant;
import com.ruoyi.charge.domain.vo.NearByChargingStationVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.ruoyi.charge.mapper.ChargingStationMapper;
import com.ruoyi.charge.domain.ChargingStation;
import com.ruoyi.charge.service.IChargingStationService;
import org.springframework.util.ObjectUtils;

/**
 * 充电站Service业务层处理
 *
 * @author ruoyi
 * @date 2022-11-10
 */
@Service
public class ChargingStationServiceImpl implements IChargingStationService {
    @Autowired
    private ChargingStationMapper chargingStationMapper;

    @Autowired
    RedisTemplate redisTemplate;

    /**
     * 查询附近充电站
     *
     * @param longitude 用户的经度
     * @param latitude  用户的纬度
     * @param radius    范围
     * @return
     */
    @Override
    public List<NearByChargingStationVO> selectNearByChargingStation(
            double longitude, double latitude, double radius) {
        //Point(double x, double y)，用户位置，经纬度，创建用户位置的坐标点
        Point userPosition = new Point(longitude, latitude);
        //Metrics，创建用户位置为圆心、半径单位为千米的圆
        //Distance(double value, Metric metric)
        Distance distance = new Distance(radius, Metrics.KILOMETERS);
        //Circle(Point center, Distance radius)
        Circle circle = new Circle(userPosition, distance);
        //public static GeoRadiusCommandArgs newGeoRadiusArgs()
        //创建获取附近充电站的查询参数
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs =
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        geoRadiusCommandArgs.includeCoordinates();//设置返回的充电站包括坐标信息
        geoRadiusCommandArgs.includeDistance();//设置返回的充电站包含距离信息
        BoundGeoOperations boundGeoOperations =
                redisTemplate.boundGeoOps(GlobalConstant.STATION_GEO_ZSET);
        //获取redis中附近的充电站
        //String是充电站编号的类型
//        GeoResults<GeoLocation<M>> geoRadius(
//                Circle within, GeoRadiusCommandArgs args)
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults =
                boundGeoOperations.radius(circle, geoRadiusCommandArgs);
        System.out.println(geoResults);
        //获取Redis缓存中充电站的详细信息
        BoundHashOperations boundHashOperations =
                redisTemplate.boundHashOps(GlobalConstant.STATION_DETAIL_HASH);
        ArrayList<NearByChargingStationVO> voList = new ArrayList<>();
        Iterator<GeoResult<RedisGeoCommands.GeoLocation<String>>> iterator =
                geoResults.iterator();
        //遍历附近充电站结果集，构建VO对象
        while (iterator.hasNext()) {
            //取充电站
            GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult =
                    iterator.next();
            //取充电站编号
            String stationId = geoResult.getContent().getName();
            //取充电站距离
            double stationDistance = geoResult.getDistance().getValue();
            //去redis(stationDetailHash)中取充电站详情
            ChargingStation chargingStation =
                    (ChargingStation) boundHashOperations.get(stationId);
            //将充电站详细信息复制到VO对象中，并设置距离属性
            NearByChargingStationVO nearByChargingStationVO =
                    new NearByChargingStationVO();
            BeanUtils.copyProperties(chargingStation, nearByChargingStationVO);
            nearByChargingStationVO.setDistance(stationDistance);
            voList.add(nearByChargingStationVO);
        }
        return voList;
    }

    /**
     * 查询充电站
     *
     * @param id 充电站主键
     * @return 充电站
     */
    @Override
    public ChargingStation selectChargingStationById(Integer id) {
        //从数据库查询慢，先从redis中查数据
        //return chargingStationMapper.selectChargingStationById(id);
        BoundHashOperations boundHashOperations =
                redisTemplate.boundHashOps(GlobalConstant.STATION_DETAIL_HASH);
        //保证所有充电站信息在redis中，往数据库中添加信息后要立刻同步到redis
        ChargingStation chargingStation =
                (ChargingStation) boundHashOperations.get(id.toString());
        //redis中有可能查不到，redis也有可能宕机了，判断是否为空
        if (ObjectUtils.isEmpty(chargingStation)) {
            //为空，redis中没有，从数据库中查
            chargingStation = chargingStationMapper.selectChargingStationById(id);
        }
        return chargingStation;
    }

    /**
     * 查询充电站列表
     *
     * @param chargingStation 充电站
     * @return 充电站
     */
    @Override
    public List<ChargingStation> selectChargingStationList(ChargingStation chargingStation) {
        return chargingStationMapper.selectChargingStationList(chargingStation);
    }

    /**
     * 新增充电站
     *
     * @param chargingStation 充电站
     * @return 结果
     */
    @Override
    public int insertChargingStation(ChargingStation chargingStation) {
        return chargingStationMapper.insertChargingStation(chargingStation);
    }

    /**
     * 修改充电站
     *
     * @param chargingStation 充电站
     * @return 结果
     */
    @Override
    public int updateChargingStation(ChargingStation chargingStation) {
        return chargingStationMapper.updateChargingStation(chargingStation);
    }

    /**
     * 批量删除充电站
     *
     * @param ids 需要删除的充电站主键
     * @return 结果
     */
    @Override
    public int deleteChargingStationByIds(Integer[] ids) {
        return chargingStationMapper.deleteChargingStationByIds(ids);
    }

    /**
     * 删除充电站信息
     *
     * @param id 充电站主键
     * @return 结果
     */
    @Override
    public int deleteChargingStationById(Integer id) {
        return chargingStationMapper.deleteChargingStationById(id);
    }
}
